<script setup lang="ts">
import { AnimatorModule, App, ButtonGroupControl, EventModule, Entity, Service, Tween, animation, explodeGroup, generateUUID } from "vjmap3d";
import { onMounted } from "vue";
import { DirectionalLight, MeshPhysicalMaterial, Plane, RepeatWrapping, Vector3 } from "three";
import "vjmap3d/dist/vjmap3d.min.css"


onMounted(async () => {
  const env = {
    serviceUrl: "https://vjmap.com/server/api/v1",
    accessToken: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJJRCI6MiwiVXNlcm5hbWUiOiJhZG1pbjEiLCJOaWNrTmFtZSI6ImFkbWluMSIsIkF1dGhvcml0eUlkIjoiYWRtaW4iLCJCdWZmZXJUaW1lIjo4NjQwMCwiZXhwIjo0ODEzMjY3NjM3LCJpc3MiOiJ2am1hcCIsIm5iZiI6MTY1OTY2NjYzN30.cDXCH2ElTzU2sQU36SNHWoTYTAc4wEkVIXmBAIzWh6M",
  };
  let svc = new Service(env.serviceUrl, env.accessToken)
  let app = new App(svc, {
    container: "map",
    render: {
      // @ts-ignore
      alpha: true,
      //  clearColor: "#000117",
      antialias: true,
      logarithmicDepthBuffer: false,
      //  stencil: false,
      //   depth: false
      // clearColorAlpha: 0
    },
    stat: {
      show: true,
      left: "0"
    },
    scene: {
      showAxesHelper: false,
      axesHelperSize: 1,
      gridHelper: {
        visible: true,
        //side: DoubleSide,

        // followCamera: true,
        args: [1000, 1000],
        cellSize: 100,
        sectionSize: 1000
      },
      // roomEnvironment: true,
    },
    ui: {
      configPane: {
        title: "配置",
        // 
        style: {
          right: '5px',
          top: "10px",
          //width: "300px"
        }
      }
    },
    coordSystem: {
      //  centerOrigin: new Vector3(587617000.8339591, 3103899303.1920567, 0)
    },
    // postProcess: {
    //     enable: true
    // },
    control: {
      //dblClickSetToCenter: false
      // leftButtonPan: true
      // verticalDragToForward: true
      // eventFromInputModule: true
    },
    camera: {
      isOrthographicCamera: false,
      near: 0.01,
      far: 1000,
      autoNearFar: false,
      position: new Vector3(-1, 3.5, 2),
      viewHelper: {
        enable: true,
        position: "leftBottom"
      }
    },
    postProcess: {
      enable: true,
      useFXAA: false,
      useSMAA: false,
      renderTargetOptions: {
          multisampling: 8
      }
    }
  })

  let scale = 0.01
  let allResources = await app.loadResources([
    {
      name: "turbine",
      url: "./turbine.glb",
      type: "model",
      options: {
        splitSubEntity: true,
        scale: scale
      }
    },
    {
      name: "equipment",
      url: "./equipment.glb",
      type: "model",
      options: {
        splitSubEntity: true,
        scale: scale
      }
    },
    {
      name: "plane",
      url: "./plane.glb",
      type: "model",
      options: {
        splitSubEntity: true,
        scale: scale
      }
    }
  ], {
        // showShadertoy: false,
        // showLabel: false,
        showHtml: true
    })
  // 加载灯光
  const loadLights = () => {
    const LIGHT_LIST = [
      [100, 100, 100],
      [-100, 100, 100],
      [100, -100, 100],
      [100, 100, -100],
    ]
    LIGHT_LIST.forEach(([x, y, z]) => {
      const directionalLight = new DirectionalLight(0xffffff, 3)
      directionalLight.position.set(x, y, z)
      app.scene.add(directionalLight)
    })
  }
  loadLights()

  let view = {
    cameraTarget: new Vector3(-1.0060227337332748, 91.7790439968262, 5.303163317193221),
    cameraPosition: new Vector3(-11.846931484584779, 107.80741258417372, 38.40723705366031),
    cameraZoom: 1,
  }
  app.cameraControl.loadState(view)

  let model = new Entity();
  let modelSkeleton = allResources.getModel("turbine");
  modelSkeleton.addTo(model);
  // console.log(modelSkeleton)
  //ent.addEdges(undefined, true)


  let mod = modelSkeleton.getModule(AnimatorModule);
  if (mod) {
    let animator = mod.getAnimator();
    animator.play(0)
  }

  let modelEquipment = allResources.getModel("equipment");
  modelEquipment.addTo(model);

  model.addTo(app)

  modelEquipment.getMeshEntities().forEach(ent => {
    ent.add(EventModule, {
          clickHighlight: true,
          highlightColor: "#ff0000",
          highlightOpacity: 0.2,
          hoverSelect: true,
          hoverHtmlText: ent.node.name,
         // clickHtmlText: ent.node.name,
          popupOptions: {
              backgroundColor: "#9FFCFD",
              anchor: "top-left"
          }
      })
  })
  let modelPlane = allResources.getModel("plane");
  modelPlane.addTo(app);

  // 允许裁剪
  app.renderer.localClippingEnabled = true

  // @ts-ignore
  window.app = app;
  const skeletonAnimation = () => {

    const MODEL_SKELETON_ENUM = {
      WireframeMaterial: '线框材质',
      ColorMaterial: '颜色材质',
    } as const


    let shellModel = modelSkeleton.getEntityByName(MODEL_SKELETON_ENUM.ColorMaterial)
    let box3d = shellModel.getBoundingBox()
    const clippingPlane = new Plane(new Vector3(0, -1, 0), box3d.max.y)
    let material = new MeshPhysicalMaterial({
      color: 0xffffff,
      metalness: 1,
      roughness: 0.7,
    })
    // 白色外壳消隐效果
    material.clippingPlanes = [clippingPlane]
    shellModel.replaceMaterial(material)
    new Tween({ value: box3d.max.y }).to(3000, { value: box3d.min.y }, {
      easing: 'linear',
      onProgress: (targe: any, key) => {
        clippingPlane.constant = targe[key]
      }, onComplete: () => {
        shellModel.remove()
      },
    }).start();

  }
  skeletonAnimation()


  // 风机平台动画
  const planeAnimation = () => {
    let obj = modelPlane.getObjectByName("polySurface136");
    if (!obj) return
    // @ts-ignore
    const texture = obj.material.map
    texture.wrapS = RepeatWrapping
    texture.wrapT = RepeatWrapping
    app.signal.onAppRender.add(() => {
      const count = texture.repeat.y
      if (count <= 10) {
        texture.repeat.x += 0.01
        texture.repeat.y += 0.02
      } else {
        texture.repeat.x = 0
        texture.repeat.y = 0
      }
    })
  }
  planeAnimation()



  let animId = generateUUID()
  // 地面和风机骨架消隐藏
  const groundAndSkeletonHideAnimation = () => {
    // modelSkeleton
    // modelPlane
    animation({
      id: animId,
      duration: 1500,
       // @ts-ignore
      onProgress(target, key, start, end, alpha) {
        modelSkeleton.getMeshEntities().forEach(mesh => {
          // @ts-ignore
          mesh.node.material.transparent = true;
          // @ts-ignore
          mesh.node.material.opacity = 1 - alpha;
        })
        modelPlane.getMeshEntities().forEach(mesh => {
          // @ts-ignore
          mesh.node.material.transparent = true;
          // @ts-ignore
          mesh.node.material.opacity = 1 - alpha;
        })
      },
      onComplete() {
        modelSkeleton.visible = false;
        modelPlane.visible = false;
      }
    })
  
    
  }
  // 地面和风机骨架显示
  const groundAndSkeletonShowAnimation = () => {
    // modelSkeleton
    // modelPlane
    animation({
      id: animId,
      duration: 1500,
      onStart() {
        modelSkeleton.visible = true;
        modelPlane.visible = true;
      },
      onUpdate(target) {
        modelSkeleton.getMeshEntities().forEach(mesh => {
          // @ts-ignore
          mesh.node.material.transparent = true;
          // @ts-ignore
          mesh.node.material.opacity = target.value;
        })
        modelPlane.getMeshEntities().forEach(mesh => {
          // @ts-ignore
          mesh.node.material.transparent = true;
          // @ts-ignore
          mesh.node.material.opacity = target.value;
        })
      }
    })
  }

  

  let explodObject = modelEquipment.node.children[0]
  let ep = explodeGroup(explodObject)
  let control = new ButtonGroupControl({
    buttons: [
      {
        id: 'reset-settings',
        html: "分解",
        title: '设备分解',
        style: {
          width: "30px"
        },
        onclick: async () => {
          groundAndSkeletonHideAnimation();
          ep.explode({
            distance: 500,
            time: 1000
          })
          app.cameraControl.loadState({
            cameraTarget: new Vector3(2.574291971568262,91.7790439968262, 1.5007042610045094),
            cameraPosition: new Vector3(-18.443047436531202,100.18131110618056, -2.3411805338779277),
            cameraZoom: 1
          }, true)
        },
      },
      {
        id: 'clear-scene',
        icon: "合成",
        title: '设备合成',
        style: {
          width: "30px"
        },
        onclick: async () => {
          ep.reset({
            time: 1000
          })
          groundAndSkeletonShowAnimation()
        },
      },
    ],
    direction: "column",
    //barSelectMode: true,
    //barCurSelectId: "reset-settings"
    //  lightTheme: true
  });
  app.addControl(control, "top-right")

})
</script>

<template>
  <div id="map"></div>
</template>

<style>
#map {
  position: absolute;
  height: 100%;
  width: 100%;
}
</style>
